//
//  ASCollectionVConfig.swift
//  soapp
//
//  Created by zhu xietong on 2018/4/24.
//

import Foundation
import AsyncDisplayKit




private extension NSObject
{
    private struct collectionconfig_keys {
        static var collectionconfig = "ascollectionconfig_key"
    }
    
    var __collectionconfig: NSMutableDictionary {
        get {
            
            if let obj = objc_getAssociatedObject(self, &collectionconfig_keys.collectionconfig) as? NSMutableDictionary
            {
                return obj
            }
            else
            {
                let dict = NSMutableDictionary()
                objc_setAssociatedObject(self, &collectionconfig_keys.collectionconfig, dict, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                return dict
            }
        }
    }
}



public protocol ASColDataSourceDelegate:NSObjectProtocol
{
    
    func numberOfSections(in collectionNode: ASCollectionNode) -> Int

    func collectionNode(_ collectionNode: ASCollectionNode, numberOfItemsInSection section: Int) -> Int

//    func collectionNode(_ collectionNode: ASCollectionNode, nodeBlockForItemAt indexPath: IndexPath) -> ASCellNodeBlock
    
    func collectionNode(_ collectionNode: ASCollectionNode, nodeForItemAt indexPath: IndexPath) -> ASCellNode
    
    func collectionNode(_ collectionNode: ASCollectionNode, nodeForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> ASCellNode
    
    
    func collectionNode(_ collectionNode: ASCollectionNode, sizeRangeForHeaderInSection section: Int) -> ASSizeRange
    
}
   


open class ASColDataSource:NSObject,ASCollectionDataSource,JoTableCellDelegate{
    
    
    
    public func touch(cell: Any, actionID: String, model: NSMutableDictionary) {
        
    }
    public var nodeForSupplementaryElement:((String,IndexPath) -> ASCellNode) = {_,_ in
        return ASCellNode()
        
    }

    open weak var delegate:ASColDataSourceDelegate?
    open var action:(String,NSMutableDictionary) ->Void = {_,_ in}
    
    open func configCollections(nodes:[ASCollectionNode])
    {
        for tb in nodes
        {
            tb.dataSource = self
        }
    }
    
    open func numberOfSections(in collectionNode: ASCollectionNode) -> Int {

        if let deleg = self.delegate
        {
            let num = deleg.numberOfSections(in: collectionNode)
            return num
        }
        return collectionNode.sectionCount()
    }
    
    
    open func collectionNode(_ collectionNode: ASCollectionNode, numberOfItemsInSection section: Int) -> Int {
        
  
        if let deleg = self.delegate
        {
            return deleg.collectionNode(collectionNode, numberOfItemsInSection: section)

        }
        return collectionNode.cellCount(section: section)
        
    }
    
    open func collectionNode(_ collectionNode: ASCollectionNode, nodeForItemAt indexPath: IndexPath) -> ASCellNode {


        if let deleg = self.delegate
        {
            let node = deleg.collectionNode(collectionNode, nodeForItemAt: indexPath)

            return node
        }
        
        return collectionNode.cellNode(indexPath: indexPath)
    }
    
    open func collectionNode(_ collectionNode: ASCollectionNode, nodeForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> ASCellNode {
        
        if let deleg = self.delegate
        {
            let node = deleg.collectionNode(collectionNode, nodeForSupplementaryElementOfKind: kind, at: indexPath)

            return node
        }
        return collectionNode.headerNode(section: indexPath.section)
    }
    
    
    open func collectionNode(_ collectionNode: ASCollectionNode, sizeRangeForHeaderInSection section: Int) -> ASSizeRange{
//        return ASSizeRange(min: CGSize(width: Swidth, height: 40), max: CGSize(width: Swidth, height: 40))
        if let deleg = self.delegate
        {
            let node = deleg.collectionNode(collectionNode, sizeRangeForHeaderInSection: section)

            return node
        }
        return collectionNode.headerSize(section: section)
    }

    
    
//    func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
//        let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "header", forIndexPath: indexPath)
//        return headerView
//    }
    
  
//    open func collectionNode(_ collectionNode: ASCollectionNode, nodeBlockForItemAt indexPath: IndexPath) -> ASCellNodeBlock {
//        if let deleg = self.delegate
//        {
//            return deleg.collectionNode(collectionNode,nodeForItemAt:indexPath)
//        }
//        return collectionNode.cellBlock(indexPath: indexPath, nodeBuild: ({_ in})).block
//
//    }
    
    deinit {
    }

    
}



public protocol ASCollectionVConfig:ASCollectionDelegate,JoTableCellDelegate,ASColDataSourceDelegate{
    
    var collection_config:ASColDataSource{get set}
    
    func configCollections(nodes:ASCollectionNode...)
    
}

extension ASCollectionVConfig where Self: UIViewController
{
    public var collection_config:ASColDataSource{
        get{
            if let source = __collectionconfig.object(forKey: "ascollectionconfig_key") as? ASColDataSource
            {
                return source
            }
            let source = ASColDataSource()
            source.delegate = self
            
            __collectionconfig.setObject(source, forKey: "ascollectionconfig_key" as NSCopying)
            return source
        }
        set{
            newValue.delegate = self
            __collectionconfig.setObject(newValue, forKey: "ascollectionconfig_key" as NSCopying)
        }
    }
    
    
    public func configCollections(nodes:ASCollectionNode...)
    {
        for tb in nodes
        {
            tb.delegate = self
            
        }
        self.collection_config.configCollections(nodes: nodes)
    }
    
    public func config(collections:[ASCollectionNode])
    {
        for tb in collections
        {
            tb.delegate = self
        }
        self.collection_config.configCollections(nodes: collections)
    }
    
    public func numberOfSections(in collectionNode: ASCollectionNode) -> Int {
        return collectionNode.sectionCount()
    }
    
    public func collectionNode(_ collectionNode: ASCollectionNode, numberOfItemsInSection section: Int) -> Int {
        return collectionNode.cellCount(section: section)
    }
    
    
    public func collectionNode(_ collectionNode: ASCollectionNode, nodeForItemAt indexPath: IndexPath) -> ASCellNode {
        let node = collectionNode.cellNode(indexPath: indexPath, fillModel: true, delegate: self)
        if let cnode = node as? JoCellNode{
            cnode.mo_controller = self
            cnode.delegate = self
        }

        return node
    }
    
    public func collectionNode(_ collectionNode: ASCollectionNode, nodeForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> ASCellNode {
        
        let head = collectionNode.headerNode(section: indexPath.section, fillModel: true, delegate: self)
        print("___S_S__S",head)
        
        if let cnode = head as? ASSizeRangeCell
        {
            cnode.mo_controller = self
            cnode.mo.controller = self

            cnode.delegate = self
        }
        return head
    }
    
    
    public func collectionNode(_ collectionNode: ASCollectionNode, sizeRangeForHeaderInSection section: Int) -> ASSizeRange {
        return collectionNode.headerSize(section: section)
    }
    
    
    
//    public func collectionNode(_ collectionNode: ASCollectionNode, nodeBlockForItemAt indexPath: IndexPath) -> ASCellNodeBlock {
//        weak var wself = self
//        let block = collectionNode.cellBlock(indexPath: indexPath) { (node) in
//            if let cnode = node as? JoCellNode{
//                cnode.delegate = wself
//            }
//        }
//        return block.block
//    }
}

extension ASCollectionVConfig where Self: ASDisplayNode
{
    public var collection_config:ASColDataSource{
        get{
            if let source = __collectionconfig.object(forKey: "ascollectionconfig_key") as? ASColDataSource
            {
                return source
            }
            let source = ASColDataSource()
            source.delegate = self
            
            __collectionconfig.setObject(source, forKey: "ascollectionconfig_key" as NSCopying)
            return source
        }
        set{
            newValue.delegate = self
            __collectionconfig.setObject(newValue, forKey: "ascollectionconfig_key" as NSCopying)
        }
    }
    
    
    public func configCollections(nodes:ASCollectionNode...)
    {
        for tb in nodes
        {
            tb.delegate = self
            
        }
        self.collection_config.configCollections(nodes: nodes)
    }
    
    public func config(collections:[ASCollectionNode])
    {
        for tb in collections
        {
            tb.delegate = self
            
        }
        self.collection_config.configCollections(nodes: collections)
    }
    
    public func numberOfSections(in collectionNode: ASCollectionNode) -> Int {
        return collectionNode.sectionCount()
    }
    
    public func collectionNode(_ collectionNode: ASCollectionNode, numberOfItemsInSection section: Int) -> Int {
        return collectionNode.cellCount(section: section)
    }
    
    
    public func collectionNode(_ collectionNode: ASCollectionNode, nodeForItemAt indexPath: IndexPath) -> ASCellNode {
        let node = collectionNode.cellNode(indexPath: indexPath,delegate: self)
        if let cnode = node as? JoCellNode{
            
        
            cnode.delegate = self
        }
        return node
    }
    
    public func collectionNode(_ collectionNode: ASCollectionNode, nodeForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> ASCellNode {
        let head = collectionNode.headerNode(section: indexPath.section, fillModel: true, delegate: self)
        if let cnode = head as? ASSizeRangeCell
        {
            cnode.mo.controller = mo_controller
            cnode.delegate = self
        }
        return head
        //        return nodeForSupplementaryElement(kind,indexPath)
    }
    
    public func collectionNode(_ collectionNode: ASCollectionNode, sizeRangeForHeaderInSection section: Int) -> ASSizeRange {
        return collectionNode.headerSize(section: section)
    }
    
    
    
    //    public func collectionNode(_ collectionNode: ASCollectionNode, nodeBlockForItemAt indexPath: IndexPath) -> ASCellNodeBlock {
    //        weak var wself = self
    //        let block = collectionNode.cellBlock(indexPath: indexPath) { (node) in
    //            if let cnode = node as? JoCellNode{
    //                cnode.delegate = wself
    //            }
    //        }
    //        return block.block
    //    }
}






extension ASCollectionVConfig where Self: UIView
{
    public var collection_config:ASColDataSource{
        get{
            if let source = __collectionconfig.object(forKey: "ascollectionconfig_key") as? ASColDataSource
            {
                return source
            }
            let source = ASColDataSource()
            source.delegate = self
            
            __collectionconfig.setObject(source, forKey: "ascollectionconfig_key" as NSCopying)
            return source
        }
        set{
            newValue.delegate = self
            __collectionconfig.setObject(newValue, forKey: "ascollectionconfig_key" as NSCopying)
        }
    }
    
    
    public func configCollections(nodes:ASCollectionNode...)
    {
        for tb in nodes
        {
            tb.delegate = self
            
        }
        self.collection_config.configCollections(nodes: nodes)
    }
    
    public func config(collections:[ASCollectionNode])
    {
        for tb in collections
        {
            tb.delegate = self
            
        }
        self.collection_config.configCollections(nodes: collections)
    }
    
    public func numberOfSections(in collectionNode: ASCollectionNode) -> Int {
        return collectionNode.sectionCount()
    }
    
    public func collectionNode(_ collectionNode: ASCollectionNode, numberOfItemsInSection section: Int) -> Int {
        return collectionNode.cellCount(section: section)
    }
    
    
    public func collectionNode(_ collectionNode: ASCollectionNode, nodeForItemAt indexPath: IndexPath) -> ASCellNode {
        let node = collectionNode.cellNode(indexPath: indexPath)
        if let cnode = node as? JoCellNode{
            cnode.delegate = self
        }
        return node
    }
    
    public func collectionNode(_ collectionNode: ASCollectionNode, nodeForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> ASCellNode {
        let head = collectionNode.headerNode(section: indexPath.section, fillModel: true, delegate: self)
        
        if let cnode = head as? ASSizeRangeCell
        {
            cnode.delegate = self
        }
        return head
        //        return nodeForSupplementaryElement(kind,indexPath)
    }
    
    public func collectionNode(_ collectionNode: ASCollectionNode, sizeRangeForHeaderInSection section: Int) -> ASSizeRange {
        return collectionNode.headerSize(section: section)
    }
    
    
    //    public func collectionNode(_ collectionNode: ASCollectionNode, nodeBlockForItemAt indexPath: IndexPath) -> ASCellNodeBlock {
    //        weak var wself = self
    //        let block = collectionNode.cellBlock(indexPath: indexPath) { (node) in
    //            if let cnode = node as? JoCellNode{
    //                cnode.delegate = wself
    //            }
    //        }
    //        return block.block
    //    }
}

